home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-04-21 | 4.9 KB | 133 lines | [TEXT/CCL2] |
- ;;; -*- Mode: LISP; Package: Language-Tools; Base: 10; Syntax: Common-Lisp -*-
- ;;;>>SHARED-MESSAGE
- ;;;>
- ;;;>******************************************************************************************
- ;;;> This may only be used as permitted under the license agreement under
- ;;;> which it has been distributed, and in no other way.
- ;;;>******************************************************************************************
- ;;;>
- ;;;>
- ;;; Written May 1982 by David A. Moon for use by the Common Lisp community
- ;;; Revised April 1983
-
- ;;; Examples of the use of MAPFORMS
-
- (DEFUN PRINT-SUBFORMS (FORM)
- (MAPFORMS #'(LAMBDA (FORM KIND USAGE IGNORE)
- (UNLESS (MEMQ KIND *MAPFORMS-NON-FORM-KINDS*)
- (FORMAT T "~&~S for ~S" FORM USAGE)))
- FORM))
-
- (DEFUN FREE-VARIABLES (FORM)
- (MAPFORMS #'(LAMBDA (FORM KIND IGNORE FREEVARS)
- (AND (MEMQ KIND '(SET SYMEVAL))
- (NOT (MEMQ FORM *MAPFORMS-BOUND-VARIABLES*))
- (NOT (MEMQ FORM FREEVARS))
- (PUSH FORM FREEVARS))
- FREEVARS)
- FORM ':BOUND-VARIABLES NIL))
-
- (DEFUN FIND-ALL-CONSTANTS (FORM)
- (MAPFORMS #'(LAMBDA (FORM KIND IGNORE CONSTANTS)
- (IF (EQ KIND 'QUOTE)
- (PUSHNEW FORM CONSTANTS))
- CONSTANTS)
- FORM))
-
- ;Returns a list of lists (variable-or-nil collection-type collection-type...)
- (DEFUN FIND-ALL-COLLECTIONS (FORM)
- (MAPFORMS #'(LAMBDA (FORM KIND IGNORE COLLECTIONS)
- (AND (NOT (MEMQ KIND *MAPFORMS-NON-FORM-KINDS*))
- (LISTP FORM)
- (EQ (CAR FORM) 'COLLECT)
- (LET ((VARIABLE NIL) (TYPE 'CONS) ELEM)
- (LOOP FOR (KEYWORD ARG) ON (CDDR FORM) BY 'CDDR
- WHEN (EQ KEYWORD 'INTO) DO (SETQ VARIABLE ARG)
- WHEN (EQ KEYWORD 'USING) DO (SETQ TYPE ARG))
- (OR (SETQ ELEM (ASSQ VARIABLE COLLECTIONS))
- (PUSH (SETQ ELEM (NCONS VARIABLE)) COLLECTIONS))
- (PUSHNEW TYPE (CDR ELEM))))
- COLLECTIONS)
- FORM))
-
- ;Expands all macros in the form, except those that have templates
- ;Maybe an option to do them, too??
- (DEFUN EXPAND-ALL-MACROS (FORM)
- (COPYFORMS #'(LAMBDA (FORM IGNORE IGNORE) FORM) FORM ':EXPAND-ALL-MACROS T))
-
- (DEFUN EXPAND-ALL-MACROS-AND-SUBSTS (FORM)
- (COPYFORMS #'(LAMBDA (FORM KIND IGNORE)
- (VALUES (IF (MEMQ KIND *MAPFORMS-NON-FORM-KINDS*)
- FORM
- (MACROEXPAND-1 FORM))
- NIL))
- FORM ':EXPAND-ALL-MACROS T))
-
- (DEFVAR *MAPFORMS-IN-FILE-FUNCTION*)
- (DEFVAR *MAPFORMS-IN-FILE-STATE*)
- (DEFVAR *MAPFORMS-IN-FILE-BOUND-VARIABLES*)
- (DEFVAR *MAPFORMS-IN-FILE-USAGE*)
-
- ;MAPFORMS over every form in the file
- (DEFUN MAPFORMS-IN-FILE (*MAPFORMS-IN-FILE-FUNCTION* FILENAME
- &OPTIONAL &KEY (INITIAL-STATE NIL)
- (BOUND-VARIABLES 'NO-ENV)
- (USAGE 'EVAL)
- &AUX (*MAPFORMS-IN-FILE-STATE* INITIAL-STATE)
- (*MAPFORMS-IN-FILE-BOUND-VARIABLES* BOUND-VARIABLES)
- (*MAPFORMS-IN-FILE-USAGE* USAGE))
- (WITH-OPEN-FILE (S FILENAME)
- (LET ((GENERIC-PATHNAME (SEND (SEND S ':PATHNAME) ':GENERIC-PATHNAME)))
- (FS:READ-ATTRIBUTE-LIST GENERIC-PATHNAME S)
- (COMPILER:COMPILE-FROM-STREAM S GENERIC-PATHNAME #'MAPFORMS-IN-FILE-1 NIL)
- *MAPFORMS-IN-FILE-STATE*)))
-
- (DEFSELECT MAPFORMS-IN-FILE-1
- ((:DUMP-FORM :DUMP-DEFINITION) (FORM)
- (SETQ *MAPFORMS-IN-FILE-STATE*
- (MAPFORMS *MAPFORMS-IN-FILE-FUNCTION* FORM
- ':INITIAL-STATE *MAPFORMS-IN-FILE-STATE*
- ':BOUND-VARIABLES *MAPFORMS-IN-FILE-BOUND-VARIABLES*
- ':USAGE *MAPFORMS-IN-FILE-USAGE*)))
- ; :DUMP-LAMBDA-EXPRESSION doesn't seem to be used?
- (:EVAL-FORM (FORM) (EVAL FORM)) ;eval-when (compile), hopefully undoable
- (:MACRO-EXPAND (FORM) (MACROEXPAND FORM))
- ((:INITIALIZE :FINALIZE) (&REST IGNORE) NIL)
- (:FOR-FILE () T)
- (:CONS-AREA () DEFAULT-CONS-AREA)
- (:TO-CORE-P () NIL) ;don't mung the current environment
- (:COMPILER-TYPE () NIL) ;don't set QC-FILE-IN-PROGRESS
- (:READ (STREAM EOF IGNORE) (READ STREAM NIL EOF))
- )
-
- (DEFUN FREE-VARIABLES-IN-FILE (FILENAME)
- (MAPFORMS-IN-FILE #'(LAMBDA (FORM KIND IGNORE FREEVARS)
- (AND (MEMQ KIND '(SET SYMEVAL))
- (NOT (MEMQ FORM *MAPFORMS-BOUND-VARIABLES*))
- (NOT (MEMQ FORM FREEVARS))
- (PUSH FORM FREEVARS))
- FREEVARS)
- FILENAME ':BOUND-VARIABLES NIL))
-
- ;This cheats a little and doesn't call the real LOOP parser
- ;State is alist of clause name (or LOOP itself) and number of times seen
- (DEFUN LOOP-CLAUSES-IN-FILE (FILENAME)
- (LET ((STATS (MAPFORMS-IN-FILE
- #'(LAMBDA (FORM KIND IGNORE STATS)
- (AND (NOT (MEMQ KIND *MAPFORMS-NON-FORM-KINDS*))
- (LISTP FORM)
- (EQ (CAR FORM) 'LOOP)
- (LOOP FOR KWD IN FORM DO
- (IF (OR (EQ KWD 'LOOP)
- (SETQ KWD (CAR (SI:LOOP-TASSOC KWD
- SI:LOOP-KEYWORD-ALIST))))
- (LET ((ELEM (ASSOC KWD STATS)))
- (OR ELEM (PUSH (SETQ ELEM (CONS KWD 0)) STATS))
- (INCF (CDR ELEM))))))
- STATS)
- FILENAME)))
- (FORMAT T "~&LOOP used ~D time~:P.~%" (OR (CDR (ASSQ 'LOOP STATS)) 0))
- (LOOP FOR (KWD . COUNT) IN (SORT STATS #'STRING-LESSP :KEY #'CAR)
- UNLESS (EQ KWD 'LOOP)
- DO (FORMAT T " ~A used ~D time~:P.~%" KWD COUNT))))
-